#include "aio_impl.h"
#include "../xos/head.h"
#include "../global/head.h"
#include "../socket/head.h"
#include "aio_callback_thread.h"
#include "aio_epoll_notify.h"
#include "aio_helper.h"
#include "aio_thread.h"

/////////////////////////////////////////////////////////////////////////////////////////
// 
namespace xos
{
    aio_impl::aio_impl()
    {
        m_uMaxConnectTime = 10 * 1000;
        m_uCheckInterval = 1000;
        m_pCallbackThread = 0;
        m_pCallbackObj = 0;
        m_pAioThread = 0;
        m_pCallback = 0;
        m_hKqueue = -1;
        m_nTimeout = -1;
        m_pEpollNotify = 0;
    }

    aio_impl::~aio_impl()
    {
        term();
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    int aio_impl::init()
    {
        using namespace std;
        int nRet = 0;
      
        if( 0 == nRet )
        {
            m_hKqueue = kqueue();
            if( -1 == m_hKqueue )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_pCallbackThread = new aio_callback_thread( this );
            m_pCallbackThread->init();
        }

        if( 0 == nRet )
        {
            m_pAioThread = new aio_thread( this );
            m_pAioThread->init();
        }

        if( 0 == nRet )
        {
            m_pEpollNotify = new aio_epoll_notify( this );
            nRet = m_pEpollNotify->init();
        }

        return nRet;
    }

    int aio_impl::term()
    {
        int nRet = 0;

        if( m_pAioThread )
        {
            m_pAioThread->term();
            delete m_pAioThread;
            m_pAioThread = 0;
        }

        if( m_pCallbackThread )
        {
            m_pCallbackThread->term();
            delete m_pCallbackThread;
            m_pCallbackThread = 0;
        }

        if( m_pEpollNotify )
        {
            m_pEpollNotify->term();
            delete m_pEpollNotify;
            m_pEpollNotify = 0;
        }

        if( -1 != m_hKqueue )
        {
            close( m_hKqueue );
            m_hKqueue = -1;
        }

        m_con_list.put_back_to_pool();
        m_key_pool.ReleaseAll();

        m_pCallbackObj = 0;
        m_pCallback = 0;

        return nRet;
    }

    ////////////////////////////////////////////////////////////////////////////////////
    // 

    // 
    // set callback. 
    // 
    int aio_impl::set_callback( i_callback * pCallbackThread, i_runnable * pCallback )
    {
        int nRet = 0;
        m_pCallbackObj = pCallbackThread;
        m_pCallback = pCallback;
        return nRet;
    }

    // 
    // aio request
    // 
    // m_nData[0] : enumAioType
    // 
    int aio_impl::post_request( i_msg * lpRequest )
    {
        using namespace std;
        int nRet = 0;
        m_pEpollNotify->notify( ( msg_impl * )lpRequest );
        return nRet;
    }

    // 
    // release
    // 
    int aio_impl::release()
    {
        int nRet = 0;

        term();
        put_back_lock();

        return nRet;
    }
} // xos
